import CameraController from "../CameraController";
import { ItemData } from "../Datas/Data";
import DroppedItem from "../DroppedItem";
import { Constant, ItemType } from "../Framework/Const/Constant";
import AudioManager from "../Framework/Managers/AudioManager";
import { BundleManager, Bundles } from "../Framework/Managers/BundleManager";
import { DataManager } from "../Framework/Managers/DataManager";
import { EventManager, MyEvent } from "../Framework/Managers/EventManager";
import { UIManager } from "../Framework/Managers/UIManager";
import NodeUtil from "../Framework/Utils/NodeUtil";
import { ResourceUtil } from "../Framework/Utils/ResourceUtil";
import { ZTool } from "../Framework/Utils/ZTool";
import GameManager, { GameMode } from "../GameManager";
import Supplies from "../Supplies";
import GameItemUI from "./GameItemUI";
import { InventoryType } from "./InventoryPanel";

const { ccclass, property } = cc._decorator;

@ccclass
export default class GamePanel extends cc.Component {
    public static Instance: GamePanel = null;

    TakeSuppliesButton: cc.Node = null;
    Evacuation: cc.Node = null;
    TakeSuppliesButtonLabel: cc.Label = null;
    EvacuationCountDownLabel: cc.Label = null;
    Weapon_0: GameItemUI = null;
    Weapon_1: GameItemUI = null;
    Pistol: GameItemUI = null;
    MeleeWeapon: GameItemUI = null;
    UseItem: cc.Node = null;
    UseItemFill: cc.Sprite = null;
    UseItemIcon: cc.Sprite = null;

    MapButton: cc.Node = null;
    TeamScore: cc.Node = null;
    RedTeamScoreLabel: cc.Label = null;
    BlueTeamScoreLabel: cc.Label = null;
    BottomBar: cc.Node = null;
    Joystick: cc.Node = null;
    ReturnButton: cc.Node = null;

    mapMode: boolean = false;

    onLoad() {
        GamePanel.Instance = this;
        this.TakeSuppliesButton = NodeUtil.GetNode("TakeSuppliesButton", this.node);
        this.Evacuation = NodeUtil.GetNode("Evacuation", this.node);
        this.TakeSuppliesButtonLabel = NodeUtil.GetComponent("TakeSuppliesButtonLabel", this.node, cc.Label);
        this.Weapon_0 = NodeUtil.GetComponent("Weapon_0", this.node, GameItemUI);
        this.Weapon_1 = NodeUtil.GetComponent("Weapon_1", this.node, GameItemUI);
        this.Pistol = NodeUtil.GetComponent("Pistol", this.node, GameItemUI);
        this.MeleeWeapon = NodeUtil.GetComponent("MeleeWeapon", this.node, GameItemUI);
        this.EvacuationCountDownLabel = NodeUtil.GetComponent("EvacuationCountDownLabel", this.node, cc.Label);
        this.UseItem = NodeUtil.GetNode("UseItem", this.node);
        this.UseItemFill = NodeUtil.GetComponent("UseItemFill", this.node, cc.Sprite);
        this.UseItemIcon = NodeUtil.GetComponent("UseItemIcon", this.node, cc.Sprite);
        this.TeamScore = NodeUtil.GetNode("TeamScore", this.node);
        this.RedTeamScoreLabel = NodeUtil.GetComponent("RedTeamScoreLabel", this.node, cc.Label);
        this.BlueTeamScoreLabel = NodeUtil.GetComponent("BlueTeamScoreLabel", this.node, cc.Label);
        this.MapButton = NodeUtil.GetNode("MapButton", this.node);
        this.BottomBar = NodeUtil.GetNode("BottomBar", this.node);
        this.Joystick = NodeUtil.GetNode("Joystick", this.node);
        this.ReturnButton = NodeUtil.GetNode("ReturnButton", this.node);

        this.Weapon_0.Set(InventoryType.Weapon_0);
        this.Weapon_1.Set(InventoryType.Weapon_1);
        this.Pistol.Set(InventoryType.Pistol);
        this.MeleeWeapon.Set(InventoryType.MeleeWeapon);
        // AudioManager.PlayNormalBGM(Constant.Audio.BG2);
        this.MapButton.on(cc.Node.EventType.TOUCH_START, () => { EventManager.Scene.emit(MyEvent.CameraZoomOut, 0.2); }, this);
        this.MapButton.on(cc.Node.EventType.TOUCH_END, () => { EventManager.Scene.emit(MyEvent.CameraZoomIn); }, this);
        this.MapButton.on(cc.Node.EventType.TOUCH_CANCEL, () => { EventManager.Scene.emit(MyEvent.CameraZoomIn); }, this);

        this.node.on(cc.Node.EventType.TOUCH_START, this.OnTouchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.OnTouchMove, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.OnTouchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.OnTouchEnd, this);

        this.MapButton.active = GameManager.GameMode == GameMode.ESCAPE;
        this.ReturnButton.active = GameManager.GameMode == GameMode.TEAM;
    }

    protected onDestroy(): void {
        // AudioManager.StopBGM(Constant.Audio.BG2);
    }

    protected start(): void {
        this.RefreshGameItemUI();
        this.TeamScore && (this.TeamScore.active = GameManager.GameMode == GameMode.TEAM);
    }

    supplies: Supplies = null;
    droppedItem: DroppedItem = null;

    ShowTakeSupplies(active: boolean, supplies: Supplies = null) {
        this.TakeSuppliesButton.active = active;
        this.supplies = supplies;
        this.droppedItem = null;

        if (active) {
            this.TakeSuppliesButtonLabel.string = `${ZTool.IsStringNullOrEmpty(supplies.data.PlayerName) ? supplies.data.Name : supplies.data.PlayerName}`;
        }
    }
 
    ShowTakeItem(active: boolean, droppedItem: any) {
        this.TakeSuppliesButton.active = active;
        this.supplies = null;
        this.droppedItem = droppedItem;

        if (active) {
            this.TakeSuppliesButtonLabel.string = `${droppedItem.itemData.Name}`;
        }
    }

    ShowUseItem(active: boolean, data = null, cb: Function = null) {
        this.UseItem.active = active;

        if (active) {
            cc.Tween.stopAllByTarget(this.UseItemFill);

            this.UseItemFill.fillRange = 1;

            BundleManager.LoadSpriteFrame(Bundles.Item, `${data.Type}_${data.Name}`).then((sf: cc.SpriteFrame) => {
                this.UseItemIcon.spriteFrame = sf;
                this.UseItemIcon.node.setScale(ItemData.GetScale(data.Type) * 0.7);
            });

            cc.tween(this.UseItemFill).to(data.Time, { fillRange: 0 }).call(() => {
                cb && cb(data.HP);
                this.ShowUseItem(false);
            }).start();
        } else {
            cc.Tween.stopAllByTarget(this.UseItemFill);
        }

    }

    countDown: number = 5;
    startCount: boolean = false;
    ShowEvacuation(active: boolean) {
        this.Evacuation.active = active;
        if (active) {
            this.startCount = true;
            this.countDown = 5;
        } else {
            this.startCount = false;
        }
    }

    redTeamScore: number = 0
    blueTeamScore: number = 0
    RefreshTeamScore(addRed: number = 0, addBlue: number = 0) {
        if (GameManager.IsGameOver) return;

        this.redTeamScore += addRed;
        this.blueTeamScore += addBlue;
        this.RedTeamScoreLabel.string = `${this.redTeamScore}`;
        this.BlueTeamScoreLabel.string = `${this.blueTeamScore}`;
        //胜利
        if (this.redTeamScore >= 10) {
            GameManager.IsGameOver = true;
            UIManager.Instance.ShowPanel(Constant.Panel.WinPanel);
        }
        //失败
        if (this.blueTeamScore >= 10) {
            GameManager.IsGameOver = true;
            DataManager.PlayerData.Clear();
            UIManager.Instance.ShowPanel(Constant.Panel.FailPanel, [GameManager.Instance.playerCtrl.hitBullet]);
        }
    }

    RefreshGameItemUI() {
        this.Weapon_0.Refresh();
        this.Weapon_1.Refresh();
        this.Pistol.Refresh();
        this.MeleeWeapon.Refresh();
    }

    RefreshBulletCount() {
        this.Weapon_0.RefreshBulletCount();
        this.Weapon_1.RefreshBulletCount();
        this.Pistol.RefreshBulletCount();
        this.MeleeWeapon.RefreshBulletCount();
    }

    protected update(dt: number): void {
        if (this.startCount) {
            this.countDown -= dt;
            if (this.countDown <= 0) {
                this.countDown = 0;
                this.startCount = false;
                UIManager.Instance.ShowPanel(Constant.Panel.WinPanel);
            }
            this.EvacuationCountDownLabel.string = `${this.countDown.toFixed(2)}`;
        }
    }

    touchs: cc.Touch[] = [];

    OnTouchStart(event: cc.Event.EventTouch) {
        if (!this.mapMode) return;
        if (!this.touchs.find(e => e == event.touch)) {
            this.touchs.push(event.touch);
        }
    }

    OnTouchMove(event: cc.Event.EventTouch) {
        if (!this.mapMode) return;
        if (this.touchs.length == 1) {
            CameraController.Instance.Move(event.touch.getDelta());
        }

        if (this.touchs.length >= 2) {
            let gap_0 = this.touchs[this.touchs.length - 1].getStartLocation().subtract(this.touchs[this.touchs.length - 2].getStartLocation()).len();
            let gap_1 = this.touchs[this.touchs.length - 1].getLocation().subtract(this.touchs[this.touchs.length - 2].getLocation()).len();
            let len = gap_1 - gap_0;
            let ratio = len * 0.00005 + CameraController.Instance.camera.zoomRatio;
            ratio = ZTool.Clamp(ratio, 0.2, 1);
            CameraController.Instance.camera.zoomRatio = ratio;
        }
    }

    OnMapButtonClick() {
        this.mapMode = !this.mapMode;
        this.BottomBar.active = !this.mapMode;
        this.Joystick.active = !this.mapMode;

        if (this.mapMode) {
            CameraController.Instance.ZoomOut(0.2);
            CameraController.Instance.stopFollow = true;

        } else {
            this.touchs = [];
            CameraController.Instance.ZoomIn();
            CameraController.Instance.stopFollow = false;
        }
    }

    OnTouchEnd(event: cc.Event.EventTouch) {
        if (!this.mapMode) return;
        this.touchs = this.touchs.filter(e => e != event.touch);
    }

    OnButtonClick(event: cc.Event) {
        AudioManager.PlayAudio(Constant.Audio.ButtonClick);

        switch (event.target.name) {
            case "TakeSuppliesButton":
                if (this.supplies != null) {
                    UIManager.Instance.ShowPanel(Constant.Panel.GameInventoryPanel, [`${ZTool.IsStringNullOrEmpty(this.supplies.data.PlayerName) ? this.supplies.data.Name : this.supplies.data.PlayerName}`, this.supplies.itemDatas, this.supplies.data.Taken ? 0 : this.supplies.data.Time]);
                    this.supplies.Take();
                }

                if (this.droppedItem != null) {
                    if (ItemData.IsMainGun(ItemType[`${this.droppedItem.itemData.Type}`]) && (DataManager.AddEquippedItem(InventoryType.Weapon_0, this.droppedItem.itemData) || DataManager.AddEquippedItem(InventoryType.Weapon_1, this.droppedItem.itemData))) {
                        AudioManager.PlayAudio(Constant.Audio.Equip);
                        this.droppedItem.node.destroy();
                        EventManager.Scene.emit(MyEvent.RefreshEquip);
                    } else if (ItemType[`${this.droppedItem.itemData.Type}`] == ItemType.手枪 && (DataManager.AddEquippedItem(InventoryType.Pistol, this.droppedItem.itemData))) {
                        AudioManager.PlayAudio(Constant.Audio.Equip);
                        EventManager.Scene.emit(MyEvent.RefreshEquip);
                        this.droppedItem.node.destroy();
                    } else if (ItemType[`${this.droppedItem.itemData.Type}`] == ItemType.头盔 && (DataManager.AddEquippedItem(InventoryType.Helmet, this.droppedItem.itemData))) {
                        AudioManager.PlayAudio(Constant.Audio.Equip);
                        EventManager.Scene.emit(MyEvent.RefreshEquip);
                        this.droppedItem.node.destroy();
                    } else if (ItemType[`${this.droppedItem.itemData.Type}`] == ItemType.防弹衣 && (DataManager.AddEquippedItem(InventoryType.Bulletproof, this.droppedItem.itemData))) {
                        AudioManager.PlayAudio(Constant.Audio.Equip);
                        EventManager.Scene.emit(MyEvent.RefreshEquip);
                        this.droppedItem.node.destroy();
                    } else if (DataManager.AddItemToBackpack(this.droppedItem.itemData)) {
                        this.droppedItem.node.destroy();
                    } else {
                        UIManager.ShowTip("背包已满");
                    }
                }
                break;
            case "Weapon_0":
                if (DataManager.PlayerData.Weapon_0) {
                    GameManager.Instance.playerCtrl.LoadGun(DataManager.PlayerData.Weapon_0);
                }
                break;
            case "Weapon_1":
                if (DataManager.PlayerData.Weapon_1) {
                    GameManager.Instance.playerCtrl.LoadGun(DataManager.PlayerData.Weapon_1);
                }
                break;
            case "Pistol":
                if (DataManager.PlayerData.Pistol) {
                    GameManager.Instance.playerCtrl.LoadGun(DataManager.PlayerData.Pistol);
                }
                break;
            case "MeleeWeapon":
                if (DataManager.PlayerData.MeleeWeapon) {
                    GameManager.Instance.playerCtrl.LoadGun(DataManager.PlayerData.MeleeWeapon);
                }
                break;
            case "ReloadButton":
                GameManager.Instance.playerCtrl.Reload();
                break;
            case "BackpackButton":
                UIManager.Instance.ShowPanel(Constant.Panel.GameInventoryPanel, [``, []]);
                break;
            case "UseItemCancelButton":
                this.ShowUseItem(false, null, null);
                break;
            case "ReturnButton":
                UIManager.Instance.ShowPanel(Constant.Panel.LoadingPanel, [`Start`]);
                break;
        }
    }

    protected onEnable(): void {
        EventManager.on(MyEvent.ShowTakeSupplies, this.ShowTakeSupplies, this);
        EventManager.on(MyEvent.ShowTakeItem, this.ShowTakeItem, this);
        EventManager.on(MyEvent.RefreshEquip, this.RefreshGameItemUI, this);
        EventManager.on(MyEvent.RefreshBulletCount, this.RefreshBulletCount, this);
        EventManager.on(MyEvent.Evacuation, this.ShowEvacuation, this);
    }

    protected onDisable(): void {
        EventManager.off(MyEvent.ShowTakeSupplies, this.ShowTakeSupplies, this);
        EventManager.off(MyEvent.RefreshEquip, this.RefreshGameItemUI, this);
        EventManager.off(MyEvent.ShowTakeItem, this.ShowTakeItem, this);
        EventManager.off(MyEvent.RefreshBulletCount, this.RefreshBulletCount, this);
        EventManager.off(MyEvent.Evacuation, this.ShowEvacuation, this);
    }
}
